package com.funong.matrix.biz.base.dao;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.funong.matrix.biz.base.entity.SysDictEntity;
import com.funong.matrix.biz.base.mapper.SysDictMapper;
import com.funong.matrix.core.base.Dao;
import com.funong.matrix.core.base.FunongBaseDao;
import com.funong.matrix.core.base.FunongBaseEntity;
import com.funong.matrix.core.dto.QueryDTO;
import com.funong.matrix.core.enums.IsDeletedEnum;
import com.funong.matrix.core.utils.BusinessException;
import com.funong.matrix.core.utils.DateTimeUtil;
import com.funong.matrix.core.utils.JwtUtils;
import org.aspectj.lang.annotation.Aspect;

import java.util.List;

/**
 * <p>
 * 字典 Dao 实现类
 * </p>
 *
 * @author lincl
 * @date 2023-08-04
 */
@Dao
@Aspect
public class SysDictDao extends FunongBaseDao<SysDictMapper, SysDictEntity> {

    public IPage queryDict(QueryDTO<SysDictEntity> queryDTO) {
        SysDictEntity sysDictEntity = queryDTO.getCondition();
        // 查询条件
        LambdaQueryWrapper<SysDictEntity> lqw = SysDictEntity.gw().eq(FunongBaseEntity::getIsDeleted, IsDeletedEnum.NOT_DELETED.getValue());
        if (sysDictEntity != null) {
            lqw.eq(sysDictEntity.getParentId() != null, SysDictEntity::getParentId, sysDictEntity.getParentId());
            lqw.eq(StrUtil.isNotBlank(sysDictEntity.getDictCode()), SysDictEntity::getDictCode, sysDictEntity.getDictCode());
            lqw.eq(StrUtil.isNotBlank(sysDictEntity.getDictValue()), SysDictEntity::getDictValue, sysDictEntity.getDictValue());
            lqw.eq(sysDictEntity.getOrderNum() != null, SysDictEntity::getOrderNum, sysDictEntity.getOrderNum());
            lqw.eq(sysDictEntity.getSystemId() != null, SysDictEntity::getSystemId, sysDictEntity.getSystemId());
            lqw.like(StrUtil.isNotBlank(sysDictEntity.getDictName()), SysDictEntity::getDictName, sysDictEntity.getDictName());
            lqw.like(StrUtil.isNotBlank(sysDictEntity.getMemo()), SysDictEntity::getMemo, sysDictEntity.getMemo());
        }
        return this.page(new Page<>(queryDTO.getPageNo(), queryDTO.getPageSize()), lqw);
    }

    public SysDictEntity getDictById(Integer id) {
        return this.getById(id);
    }

    public SysDictEntity saveDict(SysDictEntity sysDictEntity) {

        sysDictEntity.setId(null);
        sysDictEntity.setCreatedAt(null);
        sysDictEntity.setUpdatedAt(null);
        sysDictEntity.setCreatedBy(null);
        sysDictEntity.setUpdatedBy(null);

        // 判断记录是否存在相同记录
        if (this.isRepeat(sysDictEntity)) {
            throw new BusinessException("存在相同记录");
        }

        if (sysDictEntity.getParentId() != 0) {
            SysDictEntity parent = this.getById(sysDictEntity.getParentId());
            sysDictEntity.setSystemId(parent.getSystemId());
        }

        // 新增
        boolean flag = save(sysDictEntity);
        if (flag) {
            return sysDictEntity;
        }

        throw new BusinessException("新增失败");
    }

    public SysDictEntity updateDict(SysDictEntity sysDictEntity) {
        if (sysDictEntity.getId() == null) {
            throw new BusinessException("没有记录ID，无法更新");
        }

        sysDictEntity.setCreatedAt(null);
        sysDictEntity.setUpdatedAt(null);
        sysDictEntity.setCreatedBy(null);
        sysDictEntity.setUpdatedBy(null);

        // 获取记录
        SysDictEntity entity = this.getById(sysDictEntity.getId());
        // 判断记录是否存在
        if (entity == null) {
            throw new BusinessException("记录不存在");
        }
        if (!entity.getParentId().equals(sysDictEntity.getParentId())) {
            throw new BusinessException("不允许变更父ID");
        }
        // 更新字段
        BeanUtil.copyProperties(sysDictEntity, entity);

        // 判断记录是否存在相同记录
        if (this.isRepeat(entity)) {
            throw new BusinessException("存在相同记录");
        }

        // 更新
        boolean flag = updateById(entity);
        if (flag) {
            return entity;
        }

        throw new BusinessException("更新失败");
    }

    public Boolean deleteDict(List<Integer> idList) {
        if (CollUtil.isEmpty(idList)) {
            return false;
        }
        return new LambdaUpdateChainWrapper<>(this.baseMapper)
                .in(SysDictEntity::getId, idList)
                .eq(SysDictEntity::getIsDeleted, IsDeletedEnum.NOT_DELETED.getValue())
                .set(SysDictEntity::getIsDeleted, IsDeletedEnum.DELETED.getValue())
                .set(SysDictEntity::getUpdatedAt, DateTimeUtil.now())
                .set(SysDictEntity::getUpdatedBy, JwtUtils.getCurrentUserName())
                .update();
    }

    public boolean isRepeat(SysDictEntity sysDictEntity) {
        LambdaQueryWrapper<SysDictEntity> lqw = SysDictEntity.gw().eq(FunongBaseEntity::getIsDeleted, IsDeletedEnum.NOT_DELETED.getValue());

        // 若是编辑，则排除本身数据
        if (sysDictEntity.getId() != null) {
            lqw.ne(SysDictEntity::getId, sysDictEntity.getId());
        }

        // 父ID
        if (ObjectUtil.isNull(sysDictEntity.getParentId())) {
            throw new BusinessException("缺少排重字段【parentId】");
        }
        lqw.eq(SysDictEntity::getParentId, sysDictEntity.getParentId());

        // 字典编码
        if (ObjectUtil.isNull(sysDictEntity.getDictCode())) {
            throw new BusinessException("缺少排重字段【dictCode】");
        }
        lqw.eq(SysDictEntity::getDictCode, sysDictEntity.getDictCode());

        return this.count(lqw) > 0;
    }

    public List<SysDictEntity> getByParentCode(int systemId, String parentCode) {
        LambdaQueryWrapper lqw = SysDictEntity.gw()
                .eq(SysDictEntity::getSystemId, systemId)
                .eq(SysDictEntity::getDictCode, parentCode)
                .eq(FunongBaseEntity::getIsDeleted, IsDeletedEnum.NOT_DELETED.getValue());
        SysDictEntity parent = this.getOne(lqw);
        if (parent == null) {
            throw new BusinessException("字典不存在");
        }
        return this.list(SysDictEntity.gw().eq(SysDictEntity::getParentId, parent.getId()).eq(FunongBaseEntity::getIsDeleted, IsDeletedEnum.NOT_DELETED.getValue()));
    }

    /**
     * 下拉选择
     *
     * @param systemId
     * @return
     */
    public List<Tree<Integer>> querySelect(Integer systemId) {
        List<SysDictEntity> list = this.list(
                SysDictEntity.gw()
                        .eq(FunongBaseEntity::getIsDeleted, IsDeletedEnum.NOT_DELETED.getValue())
                        .eq(SysDictEntity::getSystemId, systemId)
                        .select(FunongBaseEntity::getId, SysDictEntity::getParentId, SysDictEntity::getDictCode, SysDictEntity::getDictValue, SysDictEntity::getDictName, SysDictEntity::getOrderNum, SysDictEntity::getSystemId)
        );
        return TreeUtil.build(list, 0, (item, treeNode) -> {
            treeNode.setParentId(item.getParentId()).setId(item.getId()).setName(item.getDictName());
            treeNode.put("extra", item);
        });
    }
}
